package srw;
import java.awt.Color;
import java.awt.Font;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import utils.TreeUtils;
import LexParser.LexParser;
import LexParser.MystemDictionary;
import LexParser.MystemParser;
import LexParser.MystemParserFromFile;
import LexParser.handlers.SimpleNounHandler;
import LexParser.handlers.SimpleVerbHandler;

/**
 * Main JFrame and basic configurations
 * @author nata
 *
 */

@SuppressWarnings("serial")
public class MainFrame extends JFrame implements TreeFoundListerer{
	
	public static final String _FilesPath = "src/files/";
	public static final String _DictionaryFile = "dictionary.xml";
	public static final String _PropertiesTreeFile = "properties_tree.txt";

	private static final int GAP = 10;
	private static final int WIDTH = 600;
	private static final int HEIGHT = 500;
	private static final String TITLE = "Main frame";
	
	private static MainFrame _self;
	private JTextArea _info;
	private JTextField _inputField;
	private JButton _inputButton;
	private JTree _resultTree;
	private DefaultTreeModel _treeModel;

	/**
	 * basic algorithm
	 */
	private SentenceTreeBuilder _treeBuilder;
//	private SentenceTreeBuilder1 _treeBuilder;
	
	private MainFrame() {
		_self = this;
		init();
		initFrame();
	}

	/**
	 * initialize basic objects configurations
	 */
	private void init() {
		TreeUtils.readTree(_FilesPath + _PropertiesTreeFile);
		MystemDictionary mystemDictionary = new MystemDictionary();
		mystemDictionary.readMystemDictionary(_FilesPath + "mystem/adams1-2.txt");
		mystemDictionary.print();
		MystemParser mystemParser = new MystemParserFromFile(mystemDictionary);
		LexParser lexParser = new LexParser();
		lexParser.setMystemParser(mystemParser);
		lexParser.addHandler(new SimpleNounHandler());
		lexParser.addHandler(new SimpleVerbHandler());
		_treeBuilder = new SentenceTreeBuilder(lexParser);
		_treeBuilder.setListener(this);
		
	}

	/**
	 * initialize JUnit components
	 */
	private void initFrame() {
		_self.setSize(WIDTH, HEIGHT);
		setTitle(TITLE);

		JLayeredPane lp = getLayeredPane();
		
		_inputField = new JTextField();
		_inputField.setBounds(GAP, GAP, _self.getWidth() - 2 * GAP, 25);
		lp.add(_inputField);

		_inputButton = new JButton();
		_inputButton.setFont(new Font("SansSerif", Font.PLAIN, 11));
		_inputButton.setBounds(GAP, _inputField.getY() + _inputField.getHeight() + GAP, 80, 30);
		_inputButton.setText("Enter");
		
		_inputButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				readInputSentence();
			}});
		
		_inputButton.addKeyListener(new KeyListener() {

			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					readInputSentence();
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

		});
		lp.add(_inputButton);

		ScrollPane panel = new ScrollPane();
		panel.setBounds(GAP, _inputButton.getY() + _inputButton.getHeight() + GAP, _self.getWidth() - 2* GAP, 150);
		_info = new JTextArea("");
		_info.setOpaque(false);
		_info.setForeground(Color.BLACK);
		_info.setFont(new Font("SansSerif", Font.PLAIN, 12));
		_info.setEditable(false);
		_info.setBounds(panel.getX() + GAP, panel.getY() + GAP, panel.getWidth() - GAP, panel.getHeight() - GAP);
		panel.add(_info);
		lp.add(panel);
		
		_resultTree = new JTree();
		JScrollPane treepane = new JScrollPane(_resultTree);
		treepane.setBounds(GAP, _info.getY() + _info.getHeight() + GAP, _self.getWidth() - 2* GAP, 100);
		_resultTree.setVisible(false);
		lp.add(treepane);
		
	}
	
	/**
	 * this action is called when pushing the button in the frame or pressing "enter"
	 */
	private void readInputSentence() {
		String text = _inputField.getText();
		if(text.isEmpty())
			return;
		_info.append("\n" + text + "\n");
		_inputField.setText("");
		
		Vector<String> sentence = new Vector<String>();
		String[] words = text.split(" ");
		for (int i = 0; i < words.length; i++)
			sentence.addElement(words[i]);
		
		_treeBuilder.setSentenceWords(sentence);
		_treeBuilder.buildTree();
	}

	/**
	 * get the instance of the MainFrame class
	 * @return instance of the singleton MainFrame
	 */
	public static MainFrame getInstance() {
		return _self;
	}

	/**
	 * clear information text area
	 */
	public void clearInfo() {
		_info.setText("");
	}
	
	/**
	 * {@link TreeFoundListerer} method 
	 * this action is called when the result of building the tree was achieved
	 * displays the result in text mode and with a help of JTree Component
	 */
	@Override
	public boolean treeFound(WordTreeNode root) {
		WordTreeNode firstWord = root.getChildren()[0];
		printTree(firstWord);
		_info.append("\n");
		DefaultMutableTreeNode parent = new DefaultMutableTreeNode(firstWord);
		_treeModel = new DefaultTreeModel(parent);
		createJTree(parent, firstWord);
		_resultTree.setModel(_treeModel);
		_resultTree.setVisible(true);
		return true;
	}
	
	/**
	 * show information about the incorrect input in frame 
	 * this action is called when one or more word were not found in dictionary
	 */
	@Override
	public void incorrectInput(String str) {
		_info.append("Incorrect input: " + str + "\n");
	}
	
	/**
	 * displays the result tree in text mode
	 * @param t result tree
	 */
	private void printTree(WordTreeNode t) {
		_info.append("(" + t.toString());
		WordTreeNode[] children = t.getChildren();
		for (int i = 0; i < children.length; i++) {
			printTree(children[i]);
		}
		_info.append(")");
		
	}
	
	/**
	 * displays the result with a help of JTree Component
	 * @param t result tree
	 * @param p root node of JTree
	 */
	private void createJTree(DefaultMutableTreeNode t, WordTreeNode p) {
		WordTreeNode[] children = p.getChildren();
		for (int i = 0; i < children.length; i++) {
			DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(children[i]);
			_treeModel.insertNodeInto(newChild, t, i);
			createJTree(newChild,children[i]);
		}
	}
	
	/**
	 * main method
	 * creates main JFrame 
	 * @param args
	 */
	public static void main(String[] args) {
		MainFrame main = new MainFrame();
		main.setResizable(false);
		main.setLocation(300, 300);
		main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		main.setVisible(true);
		
	}
	
}
